﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Web;

namespace TEAA
{
    public class SystemManager
    {
        private static SystemManager systemManager;

        private static FileSystemManager fileSystemManager;
        private static CatalogSystemManager catalogSystemManager;
        private static IndexManager indexManager;
        private static string activeDatabase;
        private static string databaseRootLocation;

        private SystemManager()
        {
            string xmlSchemaFile = HttpContext.Current.Server.MapPath("~") + SystemProperties.XmlSchemaRelativePath;
            string xmlNamespace = SystemProperties.XmlSchemaNamespace;
            fileSystemManager = new BinaryFileSystemManager();
            catalogSystemManager = new XmlCatalogSystemManager(xmlNamespace, xmlSchemaFile);
            indexManager = IndexManager.GetIndexManager();
            databaseRootLocation = SystemProperties.SystemRootLocation;
            activeDatabase = null;
        }

        public static SystemManager GetSystemManager()
        {
            if (systemManager == null)
                systemManager = new SystemManager();
            return systemManager;
        }

        public static void ReloadSystemManager()
        {
            systemManager = new SystemManager();
        }

        #region Database
        public List<string> GetDatabases()
        {
            List<string> databases = new List<string>();
            try
            {
                databases = fileSystemManager.GetDatabases(databaseRootLocation);
            }
            catch (Exception e)
            {
                throw new Exception("Getting available databases failed! ", e);
            }
            return databases;
        }

        public void ActivateDatabase(string databaseName)
        {
            databaseRootLocation = SystemProperties.SystemRootLocation;
            try
            {
                if (GetDatabases().Contains(databaseName))
                {
                    activeDatabase = databaseName;
                    catalogSystemManager.InitializeDatabaseCatalog(databaseRootLocation, activeDatabase);
                }
                else
                {
                    throw new Exception("Selected database does not exist in system root! ");
                }
            }
            catch (Exception e)
            {
                throw new Exception("Activation of database \"" + databaseName + "\" failed! ", e);
            }
        }

        public string GetActiveDatabase()
        {
            return activeDatabase;
        }

        public void CreateDatabase(string databaseName)
        {
            bool isDatabaseFolderCreated = false;
            try
            {
                fileSystemManager.CreateNewDatabase(databaseRootLocation, databaseName);
                isDatabaseFolderCreated = true;
                catalogSystemManager.InitializeDatabaseCatalog(databaseRootLocation, databaseName);
                activeDatabase = databaseName;
            }
            catch (Exception e)
            {
                Exception exception = new Exception("CREATE DATABASE failed for database \"" + databaseName + "\"! ", e);
                UndoCreateDatabase(isDatabaseFolderCreated, exception);
            }
        }

        private void UndoCreateDatabase(bool isDatabaseFolderCreated, Exception exception)
        {
            try
            {
                if (isDatabaseFolderCreated)
                    fileSystemManager.DeleteDatabase(databaseRootLocation, activeDatabase);
            }
            catch (Exception)
            {
                throw new Exception("ROLLBACK of CREATE DATABASE failed! ", exception);
            }
            throw exception;
        }

        public void AlterDatabase(string newDatabaseName)
        {
            bool isDatabaseFolderRenamed = false;
            string oldDatabaseName = activeDatabase;
            try
            {
                if (activeDatabase == null)
                    throw new Exception("There is no database selected! ");

                fileSystemManager.RenameDatabase(databaseRootLocation, activeDatabase, newDatabaseName);
                isDatabaseFolderRenamed = true;
                catalogSystemManager.AlterDatabase(newDatabaseName);
                ActivateDatabase(newDatabaseName);
            }
            catch (Exception e)
            {
                Exception exception = new Exception("ALTER DATABASE failed for database \"" + activeDatabase + "\"! ", e);
                UndoAlterDatabase(oldDatabaseName, newDatabaseName, isDatabaseFolderRenamed, exception);
            }
        }

        private void UndoAlterDatabase(string oldDatabaseName, string newDatabaseName,
            bool isDatabaseFolderRenamed, Exception exception)
        {
            try
            {
                if (isDatabaseFolderRenamed)
                    fileSystemManager.RenameDatabase(databaseRootLocation, newDatabaseName, oldDatabaseName);
            }
            catch (Exception)
            {
                throw new Exception("ROLLBACK of ALTER DATABASE failed! ", exception);
            }
            throw exception;
        }

        public void DropDatabase()
        {
            try
            {
                if (activeDatabase == null)
                    throw new Exception("There is no database selected! ");

                fileSystemManager.DeleteDatabase(databaseRootLocation, activeDatabase);
                activeDatabase = null;
            }
            catch (Exception e)
            {
                throw new Exception("DROP DATABASE failed for database \"" + activeDatabase + "\"! ", e);
            }
        }

        public string GetdatabaseName()
        {
            try
            {
                if (activeDatabase == null)
                    throw new Exception("There is no database selected! ");

                return catalogSystemManager.GetDatabaseName();
            }
            catch (Exception e)
            {
                throw new Exception("Getting database name failed for database \"" + activeDatabase + "\"! ", e);
            }
        }

        public string GetActiveDatabasePath()
        {
            return databaseRootLocation + Path.DirectorySeparatorChar + catalogSystemManager.GetDatabaseName();
        }

        #endregion

        #region Tables
        public List<string> GetTables()
        {
            List<string> tables = new List<string>();
            try
            {
                if (activeDatabase == null)
                    throw new Exception("There is no database selected! ");

                List<string> catalogSystemTables = catalogSystemManager.GetTables();
                List<string> fileSystemTables = fileSystemManager.GetTables(databaseRootLocation, activeDatabase);
                foreach (string catalogTable in catalogSystemTables)
                {
                    if (fileSystemTables.Contains(catalogTable))
                        tables.Add(catalogTable);
                    else
                        throw new Exception("Table \"" + catalogTable + "\" has no representation in File System of database! ");
                }
            }
            catch (Exception e)
            {
                throw new Exception("Getting available tables failed for database \"" + activeDatabase + "\"! ", e);
            }
            return tables;
        }

        public void CreateTable(string tableName)
        {
            bool isTableFileCreated = false;
            try
            {
                if (activeDatabase == null)
                    throw new Exception("There is no database selected! ");

                fileSystemManager.CreateNewTable(databaseRootLocation, activeDatabase, tableName);
                isTableFileCreated = true;
                string tableFileName = tableName + fileSystemManager.GetTableFilesExtension();
                catalogSystemManager.CreateTable(tableName, tableFileName);
            }
            catch (Exception e)
            {
                Exception exception = new Exception("CREATE TABLE failed for database \"" + activeDatabase + "\"! ", e);
                string tableFolder = tableName + fileSystemManager.GetTableFilesExtension();
                UndoCreateTable(tableFolder, isTableFileCreated, exception);
            }
        }

        private void UndoCreateTable(string tableFileName, bool isTableFileCreated, Exception exception)
        {
            try
            {
                if (isTableFileCreated)
                    fileSystemManager.DeleteTable(databaseRootLocation, activeDatabase, tableFileName);
            }
            catch (Exception)
            {
                throw new Exception("ROLLBACK of CREATE TABLE failed! ", exception);
            }
            throw exception;
        }

        public void AlterTable(string tableName, string newTableName)
        {
            bool isTableFileRenamed = false;
            try
            {
                if (activeDatabase == null)
                    throw new Exception("There is no database selected! ");

                fileSystemManager.RenameTable(databaseRootLocation, activeDatabase, tableName, newTableName);
                isTableFileRenamed = true;
                string tableFileName = newTableName + fileSystemManager.GetTableFilesExtension();
                catalogSystemManager.AlterTable(tableName, newTableName, tableFileName);
            }
            catch (Exception e)
            {
                Exception exception = new Exception("ALTER TABLE failed for database \"" + activeDatabase + "\"! ", e);
                UndoAlterTable(tableName, newTableName, isTableFileRenamed, exception);
            }
        }

        private void UndoAlterTable(string tableName, string newTableName, bool isTableFileRenamed, Exception exception)
        {
            try
            {
                if (isTableFileRenamed)
                    fileSystemManager.RenameTable(databaseRootLocation, activeDatabase, newTableName, tableName);
            }
            catch (Exception)
            {
                throw new Exception("ROLLBACK of ALTER TABLE failed! ", exception);
            }
            throw exception;
        }

        public void DropTable(string tableName)
        {
            bool isTableDeletedFromCatalog = false;
            try
            {
                if (activeDatabase == null)
                    throw new Exception("There is no database selected! ");

                catalogSystemManager.BackupDatabaseCatalog();
                catalogSystemManager.DropTable(tableName);
                isTableDeletedFromCatalog = true;
                fileSystemManager.DeleteTable(databaseRootLocation, activeDatabase, tableName);
            }
            catch (Exception e)
            {
                Exception exception = new Exception("DROP TABLE failed for database \"" + activeDatabase + "\"! ", e);
                string tableFileName = tableName + fileSystemManager.GetTableFilesExtension();
                UndoDropTable(tableName, tableFileName, isTableDeletedFromCatalog, exception);
            }
        }

        private void UndoDropTable(string tableName, string tableFileName, bool isTableDeletedFromCatalog, Exception exception)
        {
            try
            {
                if (isTableDeletedFromCatalog)
                    catalogSystemManager.RestoreDatabaseCatalog();
            }
            catch (Exception)
            {
                throw new Exception("ROLLBACK of DROP TABLE failed! ", exception);
            }
            throw exception;
        }

        public string GetTableFileName(string tableName)
        {
            try
            {
                if (activeDatabase == null)
                    throw new Exception("There is no database selected! ");

                return catalogSystemManager.GetTableFileName(tableName);
            }
            catch (Exception e)
            {
                throw new Exception("Getting table filename failed for database \"" + activeDatabase + "\"! ", e);
            }
        }

        public int GetTableRowLength(string tableName)
        {
            try
            {
                if (activeDatabase == null)
                    throw new Exception("There is no database selected! ");

                return catalogSystemManager.GetTableRowLength(tableName);
            }
            catch (Exception e)
            {
                throw new Exception("Getting table row length failed for database \"" + activeDatabase + "\"! ", e);
            }
        }

        public bool ExistsTable(string tableName)
        {
            return catalogSystemManager.ExistsTable(tableName);
        }

        public string GetTablePath(string tableName)
        {
            return GetActiveDatabasePath() + Path.DirectorySeparatorChar + tableName + Path.DirectorySeparatorChar + GetTableFileName(tableName);
        }

        #endregion

        #region Attributes

        public List<string> GetAttributes(string tableName)
        {
            List<string> attributes = new List<string>();
            try
            {
                if (activeDatabase == null)
                    throw new Exception("There is no database selected! ");

                List<string> catalogAttributes = catalogSystemManager.GetTableAttributes(tableName);
                attributes.AddRange(catalogAttributes);
            }
            catch (Exception e)
            {
                throw new Exception("Getting attributes failed for table \"" + tableName + "\" of database \"" + activeDatabase + "\"! ", e);
            }
            return attributes;
        }

        public void CreateAttribute(string tableName, string attributeName, DataType dataType, bool isNull, int length)
        {
            try
            {
                if (activeDatabase == null)
                    throw new Exception("There is no database selected! ");

                catalogSystemManager.CreateTableAttribute(tableName, attributeName, dataType, isNull, length);
            }
            catch (Exception e)
            {
                throw new Exception("CREATE ATTRIBUTE failed for database \"" + activeDatabase + "\"! ", e);
            }
        }

        public void AlterAttribute(string tableName, string attributeName, string newAttributeName, DataType newDataType, bool newIsNull, int newLength)
        {
            try
            {
                if (activeDatabase == null)
                    throw new Exception("There is no database selected! ");

                catalogSystemManager.AlterTableAttribute(tableName, attributeName, newAttributeName, newDataType, newIsNull, newLength);
            }
            catch (Exception e)
            {
                throw new Exception("ALTER ATTRIBUTE failed for database \"" + activeDatabase + "\"! ", e);
            }
        }

        public void DropAttribute(string tableName, string attributeName)
        {
            try
            {
                if (activeDatabase == null)
                    throw new Exception("There is no database selected! ");

                catalogSystemManager.DropTableAttribute(tableName, attributeName);
            }
            catch (Exception e)
            {
                throw new Exception("DROP ATTRIBUTE failed for database \"" + activeDatabase + "\"! ", e);
            }
        }

        public DataType GetAttributeDataType(string tableName, string attributeName)
        {
            try
            {
                if (activeDatabase == null)
                    throw new Exception("There is no database selected! ");

                return catalogSystemManager.GetTableAttributeDataType(tableName, attributeName);
            }
            catch (Exception e)
            {
                throw new Exception("Getting table data type failed for database \"" + activeDatabase + "\"! ", e);
            }
        }

        public bool IsAttributeIsNull(string tableName, string attributeName)
        {
            try
            {
                if (activeDatabase == null)
                    throw new Exception("There is no database selected! ");

                return catalogSystemManager.IsTableAttributeIsNull(tableName, attributeName);
            }
            catch (Exception e)
            {
                throw new Exception("Getting table is null failed for database \"" + activeDatabase + "\"! ", e);
            }
        }

        public int GetAttributeLength(string tableName, string attributeName)
        {
            try
            {
                if (activeDatabase == null)
                    throw new Exception("There is no database selected! ");

                return catalogSystemManager.GetTableAttributeLength(tableName, attributeName);
            }
            catch (Exception e)
            {
                throw new Exception("Getting attribute length failed for database \"" + activeDatabase + "\"! ", e);
            }
        }

        public bool ExistsAttribute(string tableName, string attributeName)
        {
            return catalogSystemManager.ExistsTableAttribute(tableName, attributeName);
        }

        public string GetPrimaryKey(string tableName)
        {
            string primaryKey = null;
            try
            {
                if (activeDatabase == null)
                    throw new Exception("There is no database selected! ");

                List<string> primaryKeys = catalogSystemManager.GetPrimaryKeyAttributes(tableName);
                if (primaryKeys.Count > 1)
                    throw new Exception("There is more than one attribute set as PRIMARY KEY! ");
                if (primaryKeys.Count == 1)
                    primaryKey = primaryKeys[0];
            }
            catch (Exception e)
            {
                throw new Exception("Getting PRIMARY KEY failed for table \"" + tableName + "\" of database \"" + activeDatabase + "\"! ", e);
            }
            return primaryKey;
        }

        public void SetPrimaryKey(string tableName, string attributeName)
        {
            try
            {
                if (activeDatabase == null)
                    throw new Exception("There is no database selected! ");

                if (GetPrimaryKey(tableName) == null)
                    catalogSystemManager.SetPrimaryKeyAttribute(tableName, attributeName);
                else
                    throw new Exception("There is already set an attribute as PRIMARY KEY! ");
            }
            catch (Exception e)
            {
                throw new Exception("Setting attribute as PRIMARY KEY failed for database \"" + activeDatabase + "\"! ", e);
            }
        }

        public void UnsetPrimaryKey(string tableName, string attributeName)
        {
            try
            {
                if (activeDatabase == null)
                    throw new Exception("There is no database selected! ");

                catalogSystemManager.UnsetPrimaryKeyAttribute(tableName, attributeName);
            }
            catch (Exception e)
            {
                throw new Exception("Unsetting attribute as PRIMARY KEY failed for database \"" + activeDatabase + "\"! ", e);
            }
        }

        public bool IsPrimaryKey(string tableName, string attributeName)
        {
            return catalogSystemManager.IsPrimaryKey(tableName, attributeName);
        }

        public List<string> GetUniqueKeys(string tableName)
        {
            List<string> uniqueKeys = new List<string>();
            try
            {
                if (activeDatabase == null)
                    throw new Exception("There is no database selected! ");

                List<string> uniqueKeyAttributes = catalogSystemManager.GetUniqueKeyAttributes(tableName);
                uniqueKeys.AddRange(uniqueKeyAttributes);
            }
            catch (Exception e)
            {
                throw new Exception("Getting UNIQUE KEYs failed for table \"" + tableName + "\" of database \"" + activeDatabase + "\"! ", e);
            }
            return uniqueKeys;
        }

        public void SetUniqueKey(string tableName, string attributeName)
        {
            try
            {
                if (activeDatabase == null)
                    throw new Exception("There is no database selected! ");

                catalogSystemManager.SetUniqueKeyAttribute(tableName, attributeName);
            }
            catch (Exception e)
            {
                throw new Exception("Setting attribute as UNIQUE KEY failed for database \"" + activeDatabase + "\"! ", e);
            }
        }

        public void UnsetUniqueKey(string tableName, string attributeName)
        {
            try
            {
                if (activeDatabase == null)
                    throw new Exception("There is no database selected! ");

                catalogSystemManager.UnsetUniqueKeyAttribute(tableName, attributeName);
            }
            catch (Exception e)
            {
                throw new Exception("Unsetting attribute as UNIQUE KEY failed for database \"" + activeDatabase + "\"! ", e);
            }
        }

        public bool IsUniqueKey(string tableName, string attributeName)
        {
            return catalogSystemManager.IsUniqueKey(tableName, attributeName);
        }

        public List<string> GetForeignKeys(string tableName)
        {
            List<string> foreignKeys = new List<string>();
            try
            {
                if (activeDatabase == null)
                    throw new Exception("There is no database selected! ");

                List<string> foreignKeyAttributes = catalogSystemManager.GetForeignKeyAttributes(tableName);
                foreignKeys.AddRange(foreignKeyAttributes);
            }
            catch (Exception e)
            {
                throw new Exception("Getting FOREIGN KEYs failed for table \"" + tableName + "\" of database \"" + activeDatabase + "\"! ", e);
            }
            return foreignKeys;
        }

        public void SetForeignKey(string tableName, string attributeName, string referenceTableName, string referenceAttributeName)
        {
            try
            {
                if (activeDatabase == null)
                    throw new Exception("There is no database selected! ");
                catalogSystemManager.SetForeignKeyAttribute(tableName, attributeName, referenceTableName, referenceAttributeName);
            }
            catch (Exception e)
            {
                throw new Exception("Setting attribute as UNIQUE KEY failed for database \"" + activeDatabase + "\"! ", e);
            }
        }

        public void UnsetForeignKey(string tableName, string attributeName)
        {
            try
            {
                if (activeDatabase == null)
                    throw new Exception("There is no database selected! ");

                catalogSystemManager.UnsetForeignKeyAttribute(tableName, attributeName);
            }
            catch (Exception e)
            {
                throw new Exception("Unsetting attribute as UNIQUE KEY failed for database \"" + activeDatabase + "\"! ", e);
            }
        }

        public bool IsForeignKey(string tableName, string attributeName)
        {
            return catalogSystemManager.IsForeignKey(tableName, attributeName);
        }

        public bool IsForeignKeyReference(string tableName, string attributeName)
        {
            return catalogSystemManager.IsForeignKeyReference(tableName, attributeName);
        }

        public string GetForeignKeyReferenceTable(string tableName, string foreignKeyAttribute)
        {
            try
            {
                if (activeDatabase == null)
                    throw new Exception("There is no database selected! ");

                return catalogSystemManager.GetForeignKeyReferenceTable(tableName, foreignKeyAttribute);
            }
            catch (Exception e)
            {
                throw new Exception("Getting FOREIGN KEY reference table failed for database \"" + activeDatabase + "\"! ", e);
            }
        }

        public string GetForeignKeyReferenceAttribute(string tableName, string foreignKeyAttribute)
        {
            try
            {
                if (activeDatabase == null)
                    throw new Exception("There is no database selected! ");

                return catalogSystemManager.GetForeignKeyReferenceTableAttribute(tableName, foreignKeyAttribute);
            }
            catch (Exception e)
            {
                throw new Exception("Getting FOREIGN KEY reference attribute failed for database \"" + activeDatabase + "\"! ", e);
            }
        }

        #endregion

        #region Index
        public List<string> GetIndexes(string tableName)
        {
            List<string> indexes = new List<string>();
            try
            {
                if (activeDatabase == null)
                    throw new Exception("There is no database selected! ");

                List<string> indexNames = catalogSystemManager.GetIndexes(tableName);
                indexes.AddRange(indexNames);
            }
            catch (Exception e)
            {
                throw new Exception("Getting indexes failed for table \"" + tableName + "\" of database \"" + activeDatabase + "\"! ", e);
            }
            return indexes;
        }

        public void CreateIndex(string tableName, string attributeName, IndexType indexType, bool isUnique)
        {
            bool isIndexFileCreated = false;
            try
            {
                if (activeDatabase == null)
                    throw new Exception("There is no database selected! ");

                fileSystemManager.CreateNewIndex(databaseRootLocation, activeDatabase, tableName, attributeName);
                isIndexFileCreated = true;
                string[] attributes = { attributeName };
                string indexFileName = attributeName + fileSystemManager.GetIndexFilesExtension();
                catalogSystemManager.CreateIndex(tableName, attributes, indexFileName, indexType, isUnique);

                string name = catalogSystemManager.GetIndexFileName(tableName, attributeName);

                DataType dataType = GetAttributeDataType(tableName, attributeName);
                switch (dataType)
                {
                    case DataType.Boolean:
                        indexManager.CreateIndex<bool>(name, indexType);
                        break;

                    case DataType.Integer:
                        indexManager.CreateIndex<int>(name, indexType);
                        break;

                    case DataType.Decimal:
                        indexManager.CreateIndex<double>(name, indexType);
                        break;

                    case DataType.Character:
                        indexManager.CreateIndex<char>(name, indexType);
                        break;

                    case DataType.Text:
                        indexManager.CreateIndex<string>(name, indexType);
                        break;

                    case DataType.DateTime:
                        indexManager.CreateIndex<DateTime>(name, indexType);
                        break;
                }
            }
            catch (Exception e)
            {
                Exception exception = new Exception("CREATE INDEX failed for database \"" + activeDatabase + "\"! ", e);
                UndoCreateIndex(tableName, attributeName, isIndexFileCreated, exception);
            }
        }

        private void UndoCreateIndex(string tableName, string indexName, bool isIndexFileCreated, Exception exception)
        {
            try
            {
                if (isIndexFileCreated)
                    fileSystemManager.DeleteIndex(databaseRootLocation, activeDatabase, tableName, indexName);
            }
            catch (Exception)
            {
                throw new Exception("ROLLBACK of CREATE INDEX failed! ", exception);
            }
            throw exception;
        }

        public void DropIndex(string tableName, string attributeName)
        {
            bool isIndexDeletedFromCatalog = false;
            try
            {
                if (activeDatabase == null)
                    throw new Exception("There is no database selected! ");

                catalogSystemManager.BackupDatabaseCatalog();
                string indexFileName = attributeName + fileSystemManager.GetIndexFilesExtension();
                catalogSystemManager.DropIndex(tableName, indexFileName);
                isIndexDeletedFromCatalog = true;
                fileSystemManager.DeleteIndex(databaseRootLocation, activeDatabase, tableName, attributeName);

                string name = catalogSystemManager.GetIndexFileName(tableName, attributeName);

                DataType dataType = GetAttributeDataType(tableName, attributeName);
                switch (dataType)
                {
                    case DataType.Boolean:
                        indexManager.RemoveIndex<bool>(name);
                        break;

                    case DataType.Integer:
                        indexManager.RemoveIndex<int>(name);
                        break;

                    case DataType.Decimal:
                        indexManager.RemoveIndex<double>(name);
                        break;

                    case DataType.Character:
                        indexManager.RemoveIndex<char>(name);
                        break;

                    case DataType.Text:
                        indexManager.RemoveIndex<string>(name);
                        break;

                    case DataType.DateTime:
                        indexManager.RemoveIndex<DateTime>(name);
                        break;
                }
            }
            catch (Exception e)
            {
                Exception exception = new Exception("DROP INDEX failed for database \"" + activeDatabase + "\"! ", e);
                string tableFileName = tableName + fileSystemManager.GetTableFilesExtension();
                UndoDropIndex(tableName, tableFileName, isIndexDeletedFromCatalog, exception);
            }
        }

        private void UndoDropIndex(string tableName, string attributeName, bool isIndexDeletedFromCatalog, Exception exception)
        {
            try
            {
                if (isIndexDeletedFromCatalog)
                    catalogSystemManager.RestoreDatabaseCatalog();
            }
            catch (Exception)
            {
                throw new Exception("ROLLBACK of DROP INDEX failed! ", exception);
            }
            throw exception;
        }

        public Index<T> GetIndex<T>(string tableName, string attributeName) 
        {
            string name = catalogSystemManager.GetIndexFileName(tableName, attributeName);
            return (Index<T>)indexManager.GetIndex<T>(name);
        }

        public string GetIndexFileName(string tableName, string indexAttribute)
        {
            try
            {
                if (activeDatabase == null)
                    throw new Exception("There is no database selected! ");

                return catalogSystemManager.GetIndexFileName(tableName, indexAttribute);
            }
            catch (Exception e)
            {
                throw new Exception("Getting index filename failed for database \"" + activeDatabase + "\"! ", e);
            }
        }

        public string GetIndexAttribute(string tableName, string indexFileName)
        {
            string indexAttribute = null;
            try
            {
                if (activeDatabase == null)
                    throw new Exception("There is no database selected! ");

                List<string> indexAttributes = catalogSystemManager.GetIndexAttributes(tableName, indexFileName);
                if (indexAttributes.Count > 1)
                    throw new Exception("There is more than one index attribute for index with filename \"" + indexFileName + "\"! ");
                if (indexAttributes.Count < 1)
                    throw new Exception("There is no index attribute for index with filename \"" + indexFileName + "\"! ");
                if (indexAttributes.Count == 1)
                    indexAttribute = indexAttributes[0];
            }
            catch (Exception e)
            {
                throw new Exception("Getting index attribute failed for database \"" + activeDatabase + "\"! ", e);
            }
            return indexAttribute;
        }

        public IndexType GetIndexType(string tableName, string indexFilename)
        {
            try
            {
                if (activeDatabase == null)
                    throw new Exception("There is no database selected! ");

                return catalogSystemManager.GetIndexType(tableName, indexFilename);
            }
            catch (Exception e)
            {
                throw new Exception("Getting index type failed for database \"" + activeDatabase + "\"! ", e);
            }
        }

        public bool IsIndexUnique(string tableName, string indexFilename)
        {
            try
            {
                if (activeDatabase == null)
                    throw new Exception("There is no database selected! ");

                return catalogSystemManager.IsIndexUnique(tableName, indexFilename);
            }
            catch (Exception e)
            {
                throw new Exception("Getting index is unique failed for database \"" + activeDatabase + "\"! ", e);
            }
        }

        public int GetIndexKeyLength(string tableName, string indexFilename)
        {
            try
            {
                if (activeDatabase == null)
                    throw new Exception("There is no database selected! ");

                return catalogSystemManager.GetIndexKeyLength(tableName, indexFilename);
            }
            catch (Exception e)
            {
                throw new Exception("Getting index key length failed for database \"" + activeDatabase + "\"! ", e);
            }
        }

        public bool IsIndexed(string tableName, string attributeName)
        {
            try {
                catalogSystemManager.GetIndexFileName(tableName, attributeName);
                return true;
            } 
            catch(Exception) 
            {
                return false;
            }
        }

        public string GetIndexPath(string tableName, string attributeName)
        {
            return GetActiveDatabasePath() + Path.DirectorySeparatorChar + tableName + Path.DirectorySeparatorChar + GetIndexFileName(tableName, attributeName);
        }

    }

        #endregion
}
